package com.yzion.baselib.http.progress

import com.yzion.baselib.http.progress.ProgressHelper.Companion.dispatchErrorEvent
import com.yzion.baselib.http.progress.ProgressHelper.Companion.dispatchProgressEvent
import okhttp3.MediaType
import okhttp3.ResponseBody
import okio.*
import java.io.IOException
import java.lang.ref.WeakReference

/**
 * 带进度回调的ResponseBody
 */
class ProgressResponseBody(
    private val delegate: ResponseBody,
    private val listeners: Set<WeakReference<ProgressListener>>
) : ResponseBody() {
    private var bufferedSource: BufferedSource? = null
    override fun contentType(): MediaType? {
        return delegate.contentType()
    }

    override fun contentLength(): Long {
        return delegate.contentLength()
    }

    override fun source(): BufferedSource {
        if (bufferedSource == null) {
            bufferedSource = ProgressSource(
                delegate.source()
            ).buffer()
        }
        return bufferedSource!!
    }

    internal inner class ProgressSource(delegate: Source?) : ForwardingSource(
        delegate!!
    ) {

        private var soFarBytes: Long = 0
        private var totalBytes: Long = -1

        @Throws(IOException::class)
        override fun read(sink: Buffer, byteCount: Long): Long {
            val bytesRead: Long
            try {
                bytesRead = super.read(sink, byteCount)
                if (totalBytes < 0) {
                    totalBytes = contentLength()
                }
                soFarBytes += if (bytesRead != -1L) bytesRead else 0
                dispatchProgressEvent(listeners, soFarBytes, totalBytes)
            } catch (e: IOException) {
                dispatchErrorEvent(listeners, e)
                throw e
            }
            return bytesRead
        }
    }
}